home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-05-24 | 57.6 KB | 1,492 lines |
- /************************************************************************
- *
- * HD6KER.C Superkermit main source file and driver logic.
- *
- ***********************************************************************
- *
- * In ASCII mode only:
- *
- * LF is converted to CR/LF in transmission
- * and CR, LF, CR/LF or LF/CR to LF on receipt.
- * This code is in the machine-dependent routines.
- *
- * Following enhancements by:
- *
- * Frank Dreano (Code 431)
- *
- * 2403 Tarkington Ct. or Navy Management System Support Office
- * Chesapeake, Va. 23322 1441 Crossways Boulevard
- * (804) 421-3785 Chesapeake, Va. 23320-8915
- * (804) 523-8190
- *
- * Jun 1988 - binary transfers now supported by correcting two bugs in
- * bufill() and encode()...this Kermit now precreates the right type
- * file. The PC Kermit must NOT use CTRL-Z for end-of-file marker!
- *
- * Jul 1988 - added routines to do type-1, type-2 and type-3 checksums
- * to support critical file transfers, typically binary. Also,
- * added routine to decode repeat-prefixed incoming filenames in
- * keeping with 'classic' Kermit. These routines are chk1(), chk2(),
- * chk3() and decfil() respectively.
- *
- * Aug 1988 - long packets implemented if they can be negotiated with the
- * micro Kermit, otherwise 'classic' Kermit is used. If the other side
- * can use extended packets then the length is negotiated as follows:
- *
- * If no remote extended packet length is specified but the CAPAS
- * extended bit is set then the default is 500.
- * If the remote's extended packet length is less than mine, then
- * that length is used, else mine (2000) is used.
- *
- * Changed spack() and rpack() routines to use register variables
- * and address pointer arithmetic to improve efficiency since
- * CRC integrity checks are expensive. Added a 'generic' error message
- * routine, syserr(), to send error packets for either UNIX/Kermit
- * or MOD400 type errors.
- *
- * Sep 1988 - implemented file attribute packets (definitely one of my
- * better efforts) to send file sizes back and forth for transfers; if
- * this capability is requested. This allows the user to see approximate
- * percentages of data transfered to the PC during file receives.
- * The MOD400 file size is determined by the fsize() routine and the file
- * size will NOT be estimated for variable-length record files as there
- * is NO way of knowing how many records/CI there are without reading
- * each record. If this option produces ANY problems at all turn
- * off the file attributes on the PC Kermit and bypass this feature.
- * This capability allows binary files on the DPS-6 to be precreated at
- * the right size instead of growing all over the disk in 32 Control
- * Interval file management extents. Also greatly simplified DPS-6
- * Superkermit command-line arguments and invocation.
- *
- * Dec 1988 - added support for the 4.0 operating system...the SOH char
- * is ^F for 3.1 and ^A for the 4.0 operating systems. The PC Kermit
- * can use this info to take appropriate action (e.g. to not repeat
- * the outgoing 'hide' character in 4.0 ... see notes below).
- *
- * Mar 1989 - due to Honeywell's Kermit having to run in an inefficient
- * MOD400 'swappool' under 4.0 operating system, Superkermit was made
- * more generic and now works with VIP3 and MOD400 4.0 ONLY!. The VIP3
- * Terminal Emulator must be configured for the '7-bit other host' Kermit
- * file transfer option. Although packet sizes are limited to 94 bytes
- * I feel that this is more than compensated for by Superkermit's fast
- * turn-around; no interpacket pacing delays. Superkermit also pre-
- * creates DPS-6 'fixed relative' files for binary transfers. VIP3
- * appends a ',I' string to incoming binary filenames and Superkermit
- * rips it out. Added ability to date/time stamp debug file data via
- * the new get_time() routine.
- *
- * Jan 1990 - MOD400 4.0 can now run terminal lines with eight bits of
- * data and no parity...therefore 8-bit 'binary-image' mode was
- * re-implemented for more efficient (no-prefixing) binary transfers.
- * Also made 2000-byte extended packets available for compatibility
- * with MSKermit 3.0 and up.
- *
- * Aug 1990 - fixed a problem in the nextin() routine which caused a
- * coredump when the third level of debugging (-DDD) was turned on
- * when SUPERKERMIT was receiving a file as discovered by Tim Ewing
- * from Honeywell's Maclean office.
- *
- * Sep 1990 - figured out a way to perform wild card 'sends' to a micro
- * while in server/send mode using the star_name() function. This
- * will ship up to 100 files of the type specified in the command
- * line (e.g. ASCII or BINARY); other file types will be skipped.
- * File types are: F_R = BINARY; SEQ, S_R = ASCII. This routine
- * uses the Honeywell 'heap' to build the filename list so the code
- * grew some and the compiler EC has changed (see below). Also added
- * the ability to do many 'advanced' Kermit server commands; see the
- * internal documentation below. It is strongly recommended that these
- * new capabilities only be used on a Honeywell 4.0 operating system
- * (due to Superkermit's increased size) and with MSKermit 3.02 or
- * later (3.02 fixed many 'remote' command bugs). Finally, (thanks
- * again to Tim Ewing of Honeywell Maclean) there is a way to store
- * all types of MSDOS files (e.g. text, *.COM, *.EXE, *.WKS, etc.) on
- * the DPS-6 and bring them back alive to the PC using MSKermit.
- * A new Superkermit command line argument 'F' designates a 'foreign'
- * (usually MSDOS) file type and invokes special Honeywell disk storage
- * methods. Unfortunately, the MSKermit 'remote set file type' server
- * command only has 'text' and 'binary' arguments, so to change the file
- * transfer mode to 'foreign' I have implemented a special Kermit
- * command on the micro: 'remote kermit foreign'. Modified fsize() to
- * also determine if a sequential file is being used for foreign data
- * storage so wilcard gets work correctly. Found and fixed more bugs
- * than I care to mention with fprintf() statements to the debug file.
- *
- * Performed a much-needed reorganization of code; all possible 'C'
- * preprocessor and global/external variable/functions are now in
- * a separate hd6ker.h include file. With all of these changes, the
- * program has been given a new major release number of 2.00.
- *
- * Dec 1990 - fixed a long-standing bug in binary file sending...the
- * spar() routine defaulted to a 'Y' in the 8th-bit quoting field
- * of the send-init packet; this means that I (Superkermit) do not
- * require 8th-bit quoting - a usually false assumption. Instead
- * the usual default char of '&' is now the default if no character
- * is received from the other Kermit.
- *
- * Apr 1991 - implemented the 'remote space' command as a MOD400
- * STS -ALL command as MSKermit 3.10 fixed a bug in this function.
- *
- * The above enhancements are per the Kermit Protocol Manual
- * as distributed from Columbia University, Frank da Cruz.
- *
- ***********************************************************************
- *
- * Typical ASCII file transfer (7-bit only, extended packets):
- *
- * SUPERKERM S/R/VA [file1 file2 etc.]
- *
- * Typical binary file transfer (8-bit prefixed, extended packets):
- *
- * SUPERKERM S/R/VB [file1 file2 etc.]
- *
- * MOD400 'save' files may be shipped in binary mode if the save was
- * done to a pre-created 'fixed-relative' type file.
- *
- * This Kermit has been successfully tested at speeds up to 19,200 bps
- * and also works on the Honeywell AP6 microcomputer. HOWEVER, unless
- * you KNOW that your environment can handle extended packets, CRC-type
- * block checks etc., stick to 'classic' Kermit with 94-byte packets,
- * 1-character block checks and speeds at or under 9600 bps. The PC
- * Kermit used with the DPS-6 must be modified to deliver 2 backslash
- * (\) characters when one is desired in outgoing packets as the terminal
- * driver on the Honeywell consumes the first one even in 'raw' mode.
- * This extra char should not be figured in any checksum or length
- * computations. This is only necessary with the 3.1 operating system as
- * the 'hide' char in 4.0 is ^P. If extended packets over 127-bytes are
- * desired for either the 3.1 OR the 4.0 Honeywell operating system then
- * the PC Kermit must be modified to consume incoming LF (0AH) characters
- * in its rpack() routine, these should also not be figured into checksum
- * or length computations. This is necessary as the Honeywell sends a
- * post write-order LF char at the end of 134-byte buffer writes regard-
- * less of the packet length. If these mods only activate during DPS-6
- * file transfers then the PC Kermit is still generic for all other
- * systems. These two mods were implemented in the MSSCOM.ASM module
- * of MSKERMIT Ver. 3.00 (Columbia University). This Kermit requires the
- * DPS-6 Scientific Instruction Processor or an equivalent simulator.
- *
- * WARNINGS / DISCLAIMERS / CAVEAT EMPTOR / ETC.
- * =============================================
- *
- * NO warranty is expressed or implied and the suitability of this
- * product for a particular application must be determined by the user.
- *
- * Kermit is a copyrighted product of Columbia University. As always
- * it may be freely distributed and copied as long as it remains in
- * its complete form with these comments included. This particular
- * Kermit was produced using U.S. Government time and materials.
- *
- *
- * An EC to build executable Superkermit is as follows:
- *
- * &N
- * M4_CC HD6KER.C -OP -AS -SZ 32 -V
- * M4_CC HD6PRI.C -OP -AS -SZ 32 -V
- * LD SUPERKERM -LK HD6KER HD6PRI -SZ 32 -V -NL
- * &
- * & The editor routine below saves about 9 Kwords
- * & by nuking extra 'heap' space unused by Superkermit.
- * & It also creates a more detailed link map by
- * & using the MAP versus the MAPD linker directive.
- * &
- * &A
- * >SYSLIB2>ED?SILENT
- * R SUPERKERM.Q
- * /HSIZE/ S/X'./X'B/
- * /MAPD/ S/MAPD/MAP/
- * W
- * Q
- * &D
- * >SYSLIB2>LINKER SUPERKERM -IN SUPERKERM.Q -SZ 32
- * &F
- * &Q
- *
- * If you want a 'shareable/reentrant' version append the '-R'
- * argument to the two 'M4_CC' lines and the 'LINKER' line
- * above. It will then run only in a swappool however!
- *
- ********* End of introductory comments.....Frank Dreano ************
- */
-
- #define MAINDEF /* allows the inclusion of necessary global stuff */
- #include "hd6ker.h"
- /*
- * m a i n
- *
- * main routine - parse command and options, set up the
- * tty lines, and dispatch to the appropriate routine.
- *
- */
-
- main(argc,argv)
- int argc; /* Character pointers to and count of */
- char **argv; /* command line arguments */
- {
- char *cp, **argv1;
- int argc1;
-
- unbuffer(); /* unbuffer output */
- printf("%s", ident);
- aflg = sflg = rflg = 0; /* Turn off all parse flags */
- cp = *++argv;
- argv1 = argv; /* remember argument pointers */
- argv++;
- argc1 = --argc;
- --argc; /* pointers to args */
-
- /* Initialize these values and hope the first packet will get across OK */
-
- eol = CR; /* EOL for outgoing packets */
- quote = '#'; /* Standard control-quote char "#" */
- pad = 0; /* No padding */
- padchar = NULL; /* Use xnull if any padding wanted */
- spsiz = 94; /* set up max packet length */
- qu8 = 0; /* Assume 7-bit */
- image = -1; /* ASCII file transfer */
- ofi = fileimage = ASCII; /* at first. */
- rptflg = TRUE; /* try for repeating */
- dlflag = TRUE; /* Overwrite incoming files */
- filnamcnv = FALSE; /* conversion for UNIX systems */
- sattrib = FALSE; /* attribute packets off */
- senda = TRUE; /* I have attribute capability */
- slongp = TRUE; /* extended packets on */
- dfp = 0;
- dname = 0; /* clear debug file ptrs */
- /* signal(SIGALRM,timoex); initialize signal catcher */
-
- if (argc >= 0) while ((*cp) != NULL) switch (*cp++) {
-
- /* If command-line, parse characters in first arg. */
-
- case 'H': case 'h':
- debug = 0; help(); /* H = help messages */
-
- case 'V': case 'v':
- aflg++; break; /* V = Server command */
-
- case 'I': case 'i': /* I = 8-bit image */
- image = 1;
- ++iflg; break;
-
- case 'R': case 'r':
- rflg++; break; /* R = Receive command */
-
- case 'S': case 's':
- sflg++; break; /* S = Send command */
-
- case 'F': case 'f':
- ofi++; fileimage = FOREIGN; /* B = Foreign file type */
- break;
-
- case 'B': case 'b':
- ofi++; fileimage = BINARY; /* B = Binary transfer */
- break;
-
- case 'A': case 'a':
- image = 0; /* 7 = Ascii 7-bit transfer */
- ++iflg; ofi++;
- break;
-
- case 'C': case 'c':
- dlflag = FALSE; /* C = Concat to incoming files */
- break;
-
- case '-':
- break; /* - flag swallowed */
-
- default:
- --cp;
- printmsg("Invalid char %c in command-line.",*cp);
- usage();
- }
-
- if (image == -1) { /* default is 8-bit prefixed */
- image = 2;
- ++iflg;
- }
-
- oimage = image; /* remember tseting */
- if (ofi > 1) {
- printmsg("One only of \"A\", \"B\" or \"F\" arguments!");
- usage();
- }
- ofi = fileimage; /* remember filetype */
-
- /* Flags parsed, check for debug filename */
- cp = *argv;
- if (*cp == '-') {
- if (*++cp != 'D') { /* invalid debug filename */
- printmsg("Debug filename <%s> must start with \"D\".",*--cp);
- usage();
- }
- while (*cp == 'D') { /* count the Ds */
- ++debug;
- ++cp;
- }
- if (debug > 3) usage(); /* no more than 3 'D's */
-
- dname = cp; /* filename starts after Ds */
- dfp = fopen(dname,"a");
- ++argv;
- --argc;
- }
-
- if ((c = aflg+sflg+rflg) > 1) { /* Only one command allowed */
- printmsg("One only of Server OR Receive OR Send!");
- usage();
- }
-
- if (iflg > 1) {
- printmsg("One only of \"I\" or \"A\" arguments!");
- usage();
- }
-
- if (c == 0) { /* no action-flag */
- printf(crlf);
- printmsg("No action on command-line; Server mode assumed;\n For help type \"superkerm h\".");
- aflg = 1;
- }
-
- /* Put the tty into the correct mode */
-
- rawtty();
-
- /* All set up, now execute the command that was given. */
-
- if (debug) {
- if (dfp != 0) {
- printmsg("Debugging level = %d into file \"%s\";",debug,dname);
- fprintf(dfp,"\n\n******** Superkermit Debug File ** next run starts here **********\n");
- fprintf(dfp,"%s", ident);
- get_time();
- fprintf(dfp,"\nDebugging level = %d into file \"%s\";\nCommand-line: <",debug,dname);
- while (argc1-- > 0)
- fprintf(dfp," %s",*argv1++);
- fprintf(dfp," >;");
- if (aflg) fprintf(dfp,"\nServer Command\n");
- if (sflg) fprintf(dfp,"\nSend Command\n");
- if (rflg) fprintf(dfp,"\nReceive Command\n");
- }
- else {
- printf("No valid debug file, debug switched off.\r\n");
- debug = 0;
- }
- }
-
- /* --- get BU size for operating system version and print time stanp --- */
- fsize(buname,3);
-
- if (sflg) /* Send command */
- {
- if (argc--) {
- sysint = system(tset);
- printmsg("Send Command; set your Kermit to receive files\n");
- filnam = *argv++; /* Get file to send */
- }
- else {
- cooktty(); /* restore tty to normal */
- printmsg("Send, but no filename given;\n");
- usage(); /* and give error */
- }
-
- /* check for wildcards else do the old stuff */
-
- if ((star_check(filnam)) == -1) {
- fp = NULL;
- filelist = argv; /* Set up the rest of the file list */
- filecount = argc; /* Number of files left to send */
- for (timflag=0; timflag<8; ++timflag) {sleep(1);}
- if (sendsw() == FALSE) /* Send the file(s) */
- printmsg("Send failed."); /* Report failure */
- } else {
- if (debug)
- fprintf(dfp,"\n Parsing wildcard name <%s>\n", filnam);
- wildname(filnam);
- filelist = filenames;
- if (filecount--) {
- filnam = *filelist++;
- fp = NULL;
- if (sendsw() == FALSE) { /* send the files */
- if (fp != NULL) fclose(fp);
- printmsg("Send failed."); /* Report failure */
- }
- } /* end if */
- } /* end else */
- } /* end sflag */
-
- else if (rflg) { /* Receive command */
- sysint = system(tset);
- if ((debug) && (m4_errno != 0))
- fprintf(dfp,"\nsystem call error = %d", m4_errno);
- printmsg("Receive Command; set your Kermit to Send files\n");
- for (timflag=0; timflag<5; ++timflag) {
- sleep(1);}
- timint = 20;
- if (recsw() == FALSE) /* Receive the file(s) */
- printmsg("Receive failed.");
- }
-
- else while (aflg) { /* server mode */
- sysint = system(tset);
- printmsg("Server Command; set your Kermit to Send or Get files;");
- getdir(attrib, -1); /* get users home directory */
- strcat(attrib,"/$KERMIT$.TMP");
- pthto6(attrib, fo_name);
- if (fileimage != ASCII)
- oimage = image; /* keep ORIGINAL BINARY/FOREIGN image flag */
- else oimage = 0;
- if (autosw() == TRUE) {
- printmsg("Server Send/Get complete");
- sprintf(cmdstg, ">SYSLIB2>DL %s -BF", fo_name);
- system(cmdstg);
- } else {
- /* --- logout of the DPS-6 if user requested if --- */
- printmsg("Server-mode cancelled");
- closeall();
- cooktty();
- sysint = system(tclr);
- printmsg("done.");
- system(byenow); /* Log out of DPS-6 */
- exit(0);
- } /* end else */
- }
- closeall();
- cooktty();
- sysint = system(tclr);
- printmsg("done.");
- /* if (c == 'L') system(byenow); Log out of DPS-6 if requested */
- exit(0);
- } /* End main() */
-
-
- /*
- * a u t o s w
- *
- * autosw is the state table switcher for automatic mode. It loops
- * until it finishes or an error is encountered. The called routines
- * are responsible for changing the state
- *
- */
-
- autosw() /* state switcher for automatic mode */
- {
- int len, num;
- char c, *ap, *wild;
-
- forever {
- timint = 40; /* slow NAKs at first */
- bctu = 1; /* assume type-1 blk chk at first */
- senda = TRUE;
- sattrib = FALSE; /* attribute packets off */
- if (debug) fprintf(dfp,
-
- "\nServer setup: Fileimage: %d, image: %d, q_char: %c, rptflg: %s, bchk: %d.",
- fileimage,image,qu8,logicval[-rptflg],bctu);
- /*
- "\nServersw() set: 8th-bit tseting is %d, char is %c, reptflag %s, chktype %d.",
- image,qu8,logicval[-rptflg],bctu); */
- n = numtry = 0;
- switch ( (type = rpack(&len,&num,recpkt)) ) {
- /* decipher request from micro */
-
- case 'S': /* SEND */
- /* receive file(s) from local Kermit */
- state = 'F';
- bctu = 1; /* assume type-1 blk-chk */
- rpar(recpkt,len);
- len = spar(packet);
- spack('Y',n,len,packet); /* ack parameters */
- n = (n+1)%64;
- bctu = bctr; /* use agreed upon blk-check from now on */
- while (state != 'C') { /* until EoF */
- if (debug == 1) fprintf(dfp," serversw state %c\n",state);
- switch(state) {
- case 'F': state = rfile(); break;
- case 'D': state = rdata(); break;
- case 'A': /* upload aborted */
- state = 'C'; break;
- case 'C': break;
- } } /* end switch, while */
- fileimage = ofi;
- /* If original BINARY/FOREIGN image never given default to prefixed !!! */
- if (fileimage == ASCII)
- image = 0;
- else {
- if (oimage == 0)
- image = 2;
- else
- image = oimage;
- }
- break; /* end of reception */
-
- case 'R': /* GET */
- /* send file(s) to micro Kermit */
- if (debug) fprintf(dfp,"\n getting files <%s>, ", recpkt);
- decfil(recpkt,getfiles,len);
- TYPE:
- /* process wildcards if star name else do the old stuff */
-
- if ((star_check(getfiles)) == -1)
- filecount = decol8(getfiles,filenames,10);
- else
- wildname(getfiles);
-
- filelist = filenames;
- if (debug > 1) {
- fprintf(dfp,"\n %d files, ",filecount);
- while (*filelist != 0)
- fprintf(dfp,"<%s> ",*filelist++);
- filelist = filenames;
- }
-
- if (filecount--) { /* if any valid names */
- filnam = *filelist++;
- fp = NULL;
- if (sendsw() == FALSE) { /* Send the file(s) */
- if (fp != NULL) fclose(fp);
- printmsg("Send failed."); /* Report failure */
- } /* end if */
- else
- printmsg("Files sent; still in server-mode.");
- }
- else /* if no names */
- error(noname,prompt);
- fileimage = ofi;
- /* If original BINARY/FOREIGN image never given default to prefixed !!! */
- if (fileimage == ASCII)
- image = 0;
- else {
- if (oimage == 0)
- image = 2;
- else
- image = oimage;
- }
- iflg = 0; /* reset flag to xfer and not type files */
- break;
-
- case 'I': /* INFO PACKET */
- bctu = 1; /* use type-1 blk chk at first */
- rpar(recpkt,len);
- len = spar(packet);
- spack('Y',n,len,packet); /* ack the parameters */
- bctu = bctr; /* its safe to use agreed blk chk now */
- break;
-
- case 'E': /* ERROR PACKET */
- prerrpkt(recpkt);
- aflg = 0;
- error(goodbye,prompt);
- return(FALSE);
- break;
-
- case 'N': /* NAK */
- error(amauto,prompt);
- break;
-
- case FALSE: /* TIMEOUT ON MICRO */
- printf(crlf);
- printmsg("Please enter Kermit server command to micro Kermit,");
- printf("\t(or send ESCAPE-C to cancel Superkermit) ...\n");
- spack('N',0,0,xnull);
- break;
-
- case 'G': /* KERMIT SEVER COMMAND */
- if (len > 1) {
- decfil(&recpkt[1],attrib,(len-1));
- strcpy(getfiles, &attrib[1]);
- if (debug)
- fprintf(dfp,"\nDecoded server cmd argument: %s\n", getfiles);
- }
- switch (c = *recpkt&0x5f) {
-
- case 'F': /* FINISH */
- len = strlen(goodbye);
- spack('Y',num,len,goodbye);
- aflg = 0;
- return(TRUE);
- break;
-
- case 'L': /* LOGOUT */
- len = strlen(logout);
- spack('Y',num,len,logout);
- aflg = 0;
- return(FALSE);
- break;
-
- /* --- Following routines implement advanced Kermit server features --- */
- /* --- This stuff will only work right with MSKermit 3.02 or later. --- */
- /* --- Short results are returned in a packet; long in a file xfer. --- */
-
- case 'S': /* SERVER SET FUNCTION */
- /* The 'trick' string in the next line was obtained by logging
- MSKermit 3.01/3.02 packets and not thru ANY documentation. */
- if ((strncmp(getfiles, "300!", 4)) != 0) {
- len = strlen(hostng);
- spack('Y',num,len,hostng);
- }
- else {
- len = strlen(hostok);
- spack('Y',num,len,hostok);
- if(getfiles[4] == '0') { /* Text mode */
- ofi = fileimage = ASCII;
- image = 0;
- }
- if(getfiles[4] == '1') { /* Binary mode */
- ofi = fileimage = BINARY;
- /* If original BINARY/FOREIGN image never given default to prefixed !!! */
- if (oimage == 0)
- image = 2;
- else
- image = oimage;
- } }
- break;
-
- case 'M': /* OPERATOR MESSAGE */
- case 'E': /* DELETE FILE(S) */
- case 'C': /* CHANGE WORKING DIR */
- if (c == 'C') {
- strcpy(cmdstg, getfiles);
- pthto6(cmdstg, getfiles);
- sprintf(cmdstg, ">SYSLIB2>CWD %s", getfiles);
- }
- if (c == 'E')
- sprintf(cmdstg, ">SYSLIB2>DL %s -BF", getfiles);
- if (c == 'M')
- sprintf(cmdstg, ">SYSLIB2>MSG \"%s\"", getfiles);
- cmdstat = 0;
- if ((cmdstat = system(cmdstg)) != 0) {
- if (debug)
- fprintf(dfp,
- "\nGeneric server cmd: %c, with arg: %s failed\n", c, getfiles);
- len = strlen(hostng);
- spack('Y',num,len,hostng);
- } else {
- if (debug)
- fprintf(dfp,
- "\nGeneric server cmd: %c, with arg: %s succeeded\n", c, getfiles);
- if (c == 'C')
- getcwd(cmdstg, 80);
- len = strlen(cmdstg);
- spack('Y',num,len,cmdstg);
- } /* end else */
- break;
-
- case 'T': /* TYPE A FILE */
- /* set the unused iflg variable and jump upto the 'R' to send the file */
- fileimage = ASCII; iflg = 99;
- if (debug) fprintf(dfp,"\n Typing file <%s>, ", getfiles);
- goto TYPE;
- break;
-
- case 'D': /* DIRECTORY LISTING */
- sprintf(cmdstg,">SYSLIB2>LS %s", getfiles);
- goto WHO;
- break;
- case 'W': /* WHO IS ON */
- sprintf(cmdstg,">SYSLIB2>VIDEO -G ALL -PAGES 1");
- goto WHO;
- break;
-
- case 'U': /* DISK SPACE */
- sprintf(cmdstg,">SYSLIB2>STS -ALL");
- goto WHO;
- break;
-
- default : error(onlyg,prompt);
- break;
- } /* end inner switch */
- break; /* break for outer switch */
-
- case 'K': /* SPECIAL KERMIT COMMAND */
- decfil(recpkt, getfiles, len);
- if (debug) fprintf(dfp,"\nKermit cmd: %s\n", getfiles);
- if ((strncmp("IMAGE",getfiles,5) == 0) ||
- (strncmp("image",getfiles,5) == 0)) {
- oimage = 1;
- if (fileimage != ASCII) image = 1;
- len = strlen(hostok);
- spack('Y',num,len,hostok);
- } else
- if ((strncmp("PREFI",getfiles,5) == 0) ||
- (strncmp("prefi",getfiles,5) == 0)) {
- oimage = 2;
- if (fileimage != ASCII) image = 2;
- len = strlen(hostok);
- spack('Y',num,len,hostok);
- } else
- if ((strncmp("FOREI",getfiles,5) == 0) ||
- (strncmp("forei",getfiles,5) == 0)) {
- ofi = fileimage = FOREIGN;
- /* preserve ORIGINAL image mode!!! */
- if (oimage == 0)
- image = 2;
- else
- image = oimage;
- len = strlen(hostok);
- spack('Y',num,len,hostok);
- } else
- error(onlyg, prompt);
- break;
-
- case 'C': /* MOD400 COMMAND */
-
- /* The safest way to do MOD400 commands is via I/O redirection...the DPS-6
- command results are sent to a Honeywell file (named $KERMIT$.TMP) and this
- file is then sent to the PC starting with an 'X' instead of an 'F' Kermit
- packet. This notifies MSKermit that the file should be typed to the
- microcomputer screen and not stored on disk. Unfortunately the DPS-6
- directory delimiter char is '>' which is ALSO the MSDOS I/O redirection
- symbol. MSKermit host server commands doing DPS-6 directory stuff almost
- never deliver proper directory names unless they operate only in the
- working directory. Therefore you must do things like:
- remote cwd /UDD/DREANO { UNIX style ! }
- remote host CD MYDIR
- and NOT remote host CD >>UDD>DREANO>MYDIR !!!
-
- This makes some things hard and others impossible, but thats life.
- Frank Dreano */
-
- decfil(recpkt, getfiles, len);
- filecount = decol8(getfiles,filenames,10);
- filelist = filenames;
- filecount--;
- filnam = *filelist++;
- sprintf(cmdstg, "%s", filnam);
- while (filecount-- > 0) { /* add on any command arguments */
- strcat(cmdstg," ");
- filnam = *filelist++;
- strcat(cmdstg, filnam);
- } /* end while */
- WHO:
- fileimage = ASCII; iflg = 100; /* load up the bound unit name */
- sprintf(cmdstring, ">SYSLIB2>DL %s -BF", fo_name);
- system(cmdstring);
- sleep(1);
- sprintf(cmdstring, ">SYSLIB2>FO %s", fo_name);
- system(cmdstring);
- sprintf(cmdstring, ">SYSLIB2>FO %s -EO", fo_name);
- system(cmdstring);
- if (debug) fprintf(dfp,"\nExecuting: %s \n", cmdstg);
- cmdstat = system(cmdstg);
- system(">SYSLIB2>FO -RESET -EO");
- system(">SYSLIB2>FO -RESET");
- sleep(1);
- decfil(fo_name,getfiles,strlen(fo_name));
- goto TYPE;
- break;
- /* --- --- */
- /* --- End of advanced Kermit server features --- */
- /* --- --- */
-
- default: /* BAD PACKET */
- error(badpack,prompt,type);
- return(FALSE);
- } } /* end switch, forever */
- } /* End autosw() */
-
- /*
- * b u f i l l
- *
- * Get a bufferful of data from the file thats being sent
- *
- */
-
- bufill(buffer)
- char *buffer;
- {
- int t, i;
- static int softeof= FALSE;
-
- if (softeof == TRUE) {
- softeof = FALSE;
- return(EOF);
- }
- rpt = sz = 0; /* Inits for encode() */
- dt = buffer;
- oldt = -2; /* impossible last char */
-
- if (iflg == 100) { /* skip encoding, packetizing and slew byte */
- for (i=0; i < 132 && (t=fgetc(fp)) != EOF; ++i) {
- if (i==0) continue;
- t = ascedit(t); /* edited if necessary */
- encode(t); /* to buffer */
- if (t == '\n') break;
- } /* end for */
- if (sz==0) goto EOFPROC; else return(sz);
- } else {
- while((t = getc(fp)) != EOF) { /* next character */
- t = ascedit(t); /* edited if necessary */
- encode(t); /* to buffer */
- if (sz >= spsiz-(7+bctu)) /* Check length */
- return(sz);
- } /* end while */
- } /* end else */
-
- /* reach here on (hard) EOF or error */
- EOFPROC:
- if (sz==0)
- return(EOF);
- else {
- softeof = TRUE;
- return (sz);
- }
- } /* end of bufill() */
-
- /*
- * c l o s e a l l
- *
- * Close both the input/output file and the debug file
- *
- */
-
- closeall()
- {
- if (fp != NULL)
- fclose(fp);
- if (dfp != NULL) {
- get_time(); /* print stop time to debug file */
- fprintf(dfp,"\n\n************************* End of Run ******************************\n\n");
- fclose(dfp);
- }
- } /* end of closeall() */
-
- /*
- * c r e a d
- *
- * Gets the next character from the terminal line;
- * detects Kermit escape sequences; returns SOH and
- * printables, eats all other control characters
- *
- */
-
- char cread()
- {
- char c, t;
- int ex;
-
- ex = 0;
- while (ex == 0) {
- t = nextin(); /* get next char */
- /* if (timflag == 0)
- return(0); timeout occured */
- c = t&0x7f;
- if (image != 1)
- t = c;
- if ( (c == CR) || (c == LF) || (c == SOH) || (c > 0x1f) )
- return(t);
- /* left only with invalid controls */
- if (c == ESC) { /* process escape */
- printf("\nSuperkermit-ESC");
- Repeat: /* for ignoring "-" */
- t = nextin();
- c = t&0x5f;
- if (c == SOH) return(t);
- switch(c) {
- /* case SOH:
- return(t); */
- case 'C':
- cooktty();
- printf("\nSuperkermit terminating by ESC-C from local station\n");
- closeall();
- sysint = system(tclr);
- exit(0);
- break;
- case 'H':
- printf("\n\rSuperkermit is alive and well ....\n\r");
- break;
- case 'Q':
- cooktty();
- system(tclr);
- printf("\n\rSuperkermit spawning command shell ... &Q to return\n");
- system(">SYSLIB2>EC ![TERM_ID]");
- system(tset);
- rawtty();
- break;
- case 0x1f: /* ? */
- case 0x0f: /* / */
- cooktty();
- system(tclr);
- help1();
- system(tset);
- rawtty();
- break;
- case '-':
- goto Repeat;
- default:
- printf("???");
- break;
- } } }
- return(0);
- } /* End of cread() */
-
- /*
- * d e c o d e
- *
- * Routine to decode incoming packets, returns 0 or an error-code
- *
- */
-
- decode(buf,len)
- char *buf;
- int len;
- {
- char a, a7, b8, *end, rep;
- int flg8=0, error=0, r;
-
- end = buf + len;
- while (buf < end) {
- a = *buf++;
- if ( rptflg && (a == '~') ) { /* got a repeat prefix? */
- rep = unchar(*buf++); /* Yes, get the repeat count, */
- a = *buf++;
- /* and get the prefixed character. */
- }
- else
- rep = 1;
- b8 = 0; /* Check high order "8th" bit */
- if ( (image == 2) && (a == qu8) ) {
- b8 = 0200;
- a = *buf++;
- /* and get the prefixed character. */
- }
- if (a == quote) { /* If control prefix, */
- a = *buf++; /* get its operand. */
- a7 = a & 0177; /* Only look at low 7 bits. */
- if ((a7 >= 0100 && a7 <= 0137) || a7 == '?') /* Uncontrollify */
- a = ctl(a); /* if in control range. */
- }
- a = a | b8; /* OR in the 8th bit */
-
- while (rep-- > 0) {
- if (image == 0 || fileimage == ASCII) /* if 7-bit */
- r = ascout(a);
- else { /* prefixing / image */
- r = putc(a,fp);
- }
- if (r == EOF) /* if error */
- error |= filerr();
- } }
- return(error);
- } /* end of decode() */
-
- /*
- * d e c o l 8
- *
- * Splits up command line into sections delimited by blanks,
- * zeros all such chars & places start-addresses into array,
- * up to maximum of num entries; zeros rest of entries and
- * returns count of valid entries.
- *
- */
-
- decol8(line,arr,num)
- char *line, *arr[], num;
- {
- char c, count, *start;
- int i, j;
-
- j = count = 0;
- start = line;
- for (i=0; i<80, j<num; ++i) {
- if ( (c = line[i]) <= SP) { /* terminator */
- line[i] = 0;
- if (count > 0) {
- arr[j++] = start;
- count = 0;
- }
- if (c == 0)
- break; /* out of for */
- }
- else if (count++ == 0) /* printable */
- start = &line[i]; /* start next parm */
- } /* end else, for */
- line[i] = 0; /* terminate last parm */
- i = j; /* number of parms */
- while (j < num)
- arr[j++] = 0; /* clear garbage */
- return(i);
- } /* End of decol8() */
-
- /*
- * e n c o d e
- *
- * Encode single character into packet for transmission
- *
- */
-
- encode(a)
- int a; /* char to be encoded */
- {
- int a7; /* Low order 7 bits */
- int b8; /* 8th bit of character */
- int flg8 = 0;
- static int oldsz;
-
- if (image == 2)
- flg8 = -1;
-
- if (rptflg) { /* repeat-count processing */
- if ((a == oldt) && ((a & 0x00FF) != 0xFE)) { /* char is same and NOT -2 */
-
- /* This code is simple but relatively inefficient; it stores
- the repeat flag, count and character each time around so
- that when the run is broken the buffer is valid; also it
- treats a pair as a run, which requires 3 bytes not 2 unless
- the pair is control- or 8bit-prefixed; but it does not
- require lookahead logic from the data-read. */
-
- sz = oldsz; /* wind back pointer */
- dt[sz++] = '~'; /* store prefix */
- dt[sz++] = tochar(++rpt); /* & count */
- if (rpt > 93) /* force new start */
- oldt = -2; /* impossible value */
- } /* end inner if */
- else { /* not run, or end */
- rpt = 1;
- oldt = a; /* save char */
- oldsz = sz;
- } /* end else */
- } /* end outer if */
-
- a7 = a & 0177; /* Isolate ASCII part */
- b8 = a & 0200; /* and 8th (parity) bit. */
-
- if (flg8 && b8) { /* Do 8th bit prefix if necessary. */
- dt[sz++] = qu8;
- a = a7;
- }
- if ((a7 < SP) || (a7==DEL)) { /* Do control prefix if necessary */
- dt[sz++] = MYQUOTE;
- a = ctl(a);
- }
- if (a7 == MYQUOTE) /* Prefix the control prefix */
- dt[sz++] = MYQUOTE;
- else if (rptflg && (a7 == '~')) /* If it's the repeat prefix, */
- dt[sz++] = MYQUOTE;
- /* quote it if doing repeat counts. */
- else if (flg8 && (a7 == qu8)) /* Prefix the 8th bit prefix */
- dt[sz++] = MYQUOTE; /* if doing 8th-bit prefixes */
-
- dt[sz++] = a; /* Finally, insert the character */
- dt[sz] = '\0'; /* itself, and mark the end. */
- return;
- } /* end of encode() */
-
- /*
- * g n x t f l
- *
- * Get next file in a file group
- *
- */
-
- gnxtfl()
- {
- if (debug) fprintf(dfp,"\n gnxtfl: filelist = \"%s\"",*filelist);
- filnam = *(filelist++);
- if (filecount-- == 0)
- return FALSE; /* If no more, fail */
- else
- return TRUE; /* else succeed */
- } /* End gnxtfl() */
-
- /*
- * d e c f i l
- *
- * This routine decodes repeat-prefixed, control-prefixed
- * incoming filenames and Kermit server advanced commands.
- * It assumes that such items are 7-bit ASCII ONLY !!!
- * [FRANK DREANO]
- */
-
- decfil(buf, to, len)
- char *buf, *to;
- int len;
- {
- char a, *end, rep;
- end = buf + len;
- while (buf < end) {
-
- a = *buf++;
- if (a == '~') {
- rep = unchar(*buf++);
- a = *buf++;
- } /* end if */
- else
- rep = 1;
-
- if (a == quote) {
- a = *buf++;
- a &= 0177;
- if ((a >= 0100 && a <= 0137) || a =='?')
- a = ctl(a);
- } /* end if */
-
- while (rep-- > 0)
- *to++ = a;
-
- } /* end outer while */
- *to = '\0';
- return;
- } /* end decfil */
-
- /*
- * r e c s w
- *
- * This is the state table switcher for receiving files
- *
- */
-
- recsw()
- {
- if (debug) fprintf(dfp,"Ready to receive file\n");
- state = 'R'; /* Receive-Init is the start state */
- n = 0; /* Initialize message number */
- numtry = 0; /* Say no tries yet */
-
- forever {
- if (debug == 1) fprintf(dfp," recsw state: %c\n",state);
- switch(state) /* Do until done */
- {
- case 'R': state = rinit(); break; /* Receive-Init */
- case 'F': state = rfile(); break; /* Receive-File */
- case 'D': state = rdata(); break; /* Receive-Data */
- case 'C': return(TRUE); /* Complete state */
- case 'A': return(FALSE); /* "Abort" state */
- }
- }
- } /* End recsw() */
-
- /*
- * s e n d s w
- *
- * Sendsw is the state table switcher for sending files. It loops until
- * either it finishes, or an error is encountered. The routines called
- * by sendsw are responsible for changing the state.
- */
-
- sendsw()
- {
- if (debug) {
- fprintf(dfp,"\nSendsw() sending file; ");
- }
- state = 'S'; /* Send initiate is the start state */
- n = 0; /* Initialize message number */
- numtry = 0; /* Say no tries yet */
- forever { /* Do this as long as necessary */
- if (debug == 1) fprintf(dfp," sendsw state: %c\n",state);
- switch(state) {
- /* 'Q' state is for attributes ONLY! */
- case 'Q': state = sattru(); break; /* Send-Attributes */
- case 'S': state = sinit(); break; /* Send-Init */
- case 'F': state = sfile(); break; /* Send-File */
- case 'D': state = sdata(); break; /* Send-Data */
- case 'Z': state = seof(); break; /* Send-End-of-File */
- case 'B': state = sbreak(); break; /* Send-Break */
- case 'C': return (TRUE); /* Complete */
- case 'A': return (FALSE); /* "Abort" */
- default: return (FALSE); /* Unknown, fail */
- }
- }
- } /* End sendsw() */
-
- /*
- * s y s e r r
- *
- * Routine to provide generic error reporting of either
- * UNIX or MOD400 type errors. [FRANK DREANO]
- *
- */
-
- syserr(msg)
- char *msg;
- {
- char sherr[25], errstg1[50], errstg2[10];
- int status;
- extern int errno, sys_nerr;
- extern char *sys_errlist[];
-
- /* --- print MOD400 error if its a "system" ECL command request --- */
-
- if ((status = strncmp(msg, "syst", 4)) == 0) {
- sprintf(errstg1, "%sError occurred in MOD400 command: 0%x",prompt,m4_errno);
- sprintf(sherr, ">SYSLIB2>DISPLAY 0%x", m4_errno);
- if ((status = system(sherr)) != 0)
- fprintf(stderr, "MOD400 error not in message library. \n");
- error(errstg1); /* ship error packet out */
- } /* end if */
-
- /* --- if its a UNIX type error print MOD400 equivalent, if
- possible, then print the UNIX version of the error --- */
-
- else {
- if (((m4_errno - errno) != 0x1800) && (m4_errno > 0) && (m4_errno < 0x9999)) {
- fprintf(stderr, "Error occurred in MOD400 system service call. \n");
- sprintf(sherr, ">SYSLIB2>DISPLAY 0%x", m4_errno);
- if ((status = system(sherr)) != 0)
- fprintf(stderr, "Error not in message library. \n");
- } /* end if */
- sprintf(errstg1, "%sERROR: %s (%d",prompt, msg, errno);
- if (errno > 0 && errno < sys_nerr)
- sprintf(errstg2, ": %s)\n", sys_errlist[errno]);
- else
- sprintf(errstg2,")\n");
- strcat(errstg1, errstg2);
- error(errstg1); /* send error packet out */
- } /* end else */
- } /* end syserr */
-
-
- /*
- * g e t _ t i m e
- *
- * function to print start/stop time to debug file in the form:
- * Thu May 25 07:50:15 1989
- */
-
- get_time()
- {
- struct tm { int tm_sec; int tm_min; int tm_hour; int tm_mday; int tm_mon;
- int tm_year; int tm_wday; int tm_yday; int tm_isdst; } *localtime();
- long time(), tloc;
- char *asctime(), *ltime;
- tloc = time ( (long *) 0);
- ltime = asctime(localtime(&tloc));
- if (debug) fprintf(dfp,
- "\n\t Time stamp: %s\n", ltime);
- return(0);
- } /* end get_time */
-
-
- /*
- * a s c e d i t
- *
- * This routine converts unix LF end-of-line to CR/LF
- * iff in 7-bit mode prior to sending the character.
- * Returns the modified character.
- *
- */
-
- char ascedit(c)
- char c;
- {
- if (image == 0 || fileimage == ASCII) {
- /* only if 7-bit */
- c &= 0x7f;
- if (c == LF)
- encode(CR); /* CR of CR/LF; */
- } /* bufill() adds the LF */
- return(c);
- } /* End of ascedit() */
-
- /*
- * a s c o u t
- *
- * This routine writes 7-bit data to file as it is received
- * and is not used for 8-bit data, either image or 8-prefixing
- *
- */
-
- char ascout(a)
- char a;
- {
- char ret;
- static char olda = 0;
-
- /* for dps6, replace each CR, LF or CR/LF or LF/CR by a single LF */
- if (a == SUB) {
- ret = olda = 0;
- return (ret);
- }
- if ( ( (a == CR) && (olda == LF) )
- || ( (a == LF) && (olda == CR) ) )
- ret = olda = 0;
- else { /* if not CR/LF pair */
- olda = a;
- if (a == CR)
- a = LF; /* CR => LF for unix */
- ret = putc(a,fp);
- }
- return (ret);
- } /* End of ascout() */
-
- /*
- * f i l e r r
- *
- * This routine is called when EOF is encountered reading or
- * writing the data file, if truly and EOF it returns 0 or
- * else a system error code
- *
- */
-
- char filerr()
- {
- char ret;
-
- ret = ferror(fp);
- clearerr(fp);
- return(ret);
- } /* End of flerr() */
-
- /*
- * f l u s h i n p u t
- *
- * Dump all pending input to clear stacked up NAKs
- *
- */
-
- flushinput() /* DHS 1.0 version */
- {
- /* ioctl(0,TIOCFLUSH,0); */
- return;
- } /* End of flushinput() */
-
- /*
- * c o o k t t y / r a w t t y
- *
- * Routines to set terminal input into "raw" or "cooked" mode.
- *
- */
-
- static char cookedok = 0;
-
- cooktty() /* restore terminal state */
- {
- /* if (cookedok != 0) provided made raw */
- /* stty(0,&cookedmode); */
- return;
- } /* End of cooktty */
-
- rawtty() /* set terminal raw */
- {
- if (cookedok == 0) { /* first time only */
- /* gtty(0,&cookedmode); Save current mode so we can */
- /* gtty(0,&rawmode); restore it later */
- cookedok = 1;
- rawmode.sg_flags != (RAW|TANDEM);
- rawmode.sg_flags &= ~(ECHO|CRMOD);
- }
- /* stty(0,&rawmode); Put tty in raw mode */
- return;
- } /* End of rawtty() */
-
- /* end of tty cook/uncook routines */
-
- /*
- * n e x t i n
- *
- * Timeouts are always accompanied by attempting to read
- * the line. Two situations are catered for: normally,
- * if a timeout can be set which cancels a hanging
- * read() call, then this is done; else if a test
- * can be made as to whether chars are available AND
- * a sleep() call is available, these are linked to
- * provide a timeout based on decrementing after
- * each sleep().
- */
-
- char nextin() /* read next char, checking time-flag */
- /* return char (or 0 if timer expired) */
- {
- char c;
- static char buff[2048];
- static int count = 0, cmax = 0, ccnt = 0;
- long lcount;
-
- if (count == 0)
- cmax = count = read(0, buff, 2047);
- c = buff[cmax - (count--)];
- if (debug > 2) {
- if (ccnt == 0) fprintf(dfp, "\n");
- if (ccnt > 15) {
- fprintf(dfp," %x \n",((int)c)&0xff );
- ccnt = 0;
- }
- else {
- fprintf(dfp," %x ",((int)c)&0xff );
- ++ccnt;
- }
- }
- return(c);
- } /* end of nextin() */
-
-
-
- timoset(sex) /* set timeout */
- char sex; /* # of seconds */
- {
- timflag = sex;
- /* signal(SIGALRM,timoex);
- alarm(timflag); */
- return;
- } /* End of timoset() */
-
- /* The routines which action and clear timeouts, timoex()
- and timocan() are not system-dependent; see above. */
-
- /*
- * u n b u f f e r
- *
- * System-dependent action to do quick terminal writes
- *
- */
-
- unbuffer() /* unbuffer output */
- /* system-dependent action to write quickly to terminal */
- {
- /* setbuf(stdout,0); UNbuffer output! */
- return;
- } /* End of unbuffer() */
-
- /*
- * w i l d n a m e
- *
- * Routine to retrieve Honeywell files using wildcards
- *
- */
-
- wildname(line)
- char *line;
- {
- unsigned char *sn, *fsn;
- char fnamx[MOD4_NAME-1];
- int type = 0;
- fsn = sn = star_name(line, "\0"); /* file in working dir */
- filecount = 0;
- if (*sn == 0) return(0); /* no filenames given */
- while (*sn != 0) { /* loop through star name list */
- type = *sn; /* MOD400 file type */
- sprintf(fnamx, "%s", ++sn); /* make file name into string */
- switch(type) { /* only ship files of the cmd line type! */
- case F_R:
- if (fileimage == BINARY) {
- filenames[filecount] = sn;
- filecount += 1;
- }
- break;
- case SEQ:
- case SVQ:
- if ((fsize(sn,1) != 0) &&
- (fileimage == FOREIGN)) {
- filenames[filecount] = sn;
- filecount += 1;
- }
- if ((fsize(sn,1) == 0) &&
- (fileimage == ASCII)) {
- filenames[filecount] = sn;
- filecount += 1;
- }
- break;
- case S_R:
- if (fileimage == ASCII) {
- filenames[filecount] = sn;
- filecount += 1;
- }
- break;
- default: break;
- } /* end switch; fall through if not ASCII/BINARY */
- sn += strlen(fnamx)+1; /* point to next file name */
- } /* end while */
- free(fsn); /* star_name() uses the heap; give back the mem */
- } /* end of wildname() */
-
- /********************* END of FILE hd6ker.c **************************/
-